home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / minix / libsrc~1.z / libsrc~1 / sflonum.s < prev    next >
Encoding:
Text File  |  1989-12-28  |  9.2 KB  |  450 lines

  1. |
  2. |    Single Precision Floating point support code.
  3. |
  4. |    A SP float looks like:
  5. |
  6. |    |S|E.x.p ... |M.a.n.t.i.s.s.a ... |
  7. |    +-+----------+--------------------+
  8. |
  9. |    where s is the sign bit, Exp is 8 bits of exponent, interpreted
  10. |    as E + 126, and Mantissa is 23 bits of fraction, with a
  11. |    hidden bit.  The point is to the left of the hidden bit.
  12. |    Doubles have another word of mantissa following.
  13. |
  14. |    All these routines have calling sequences like c routines,
  15. |    ie args on stack in backwards order, return values in d0
  16. |
  17.  
  18. #ifdef L_addsf3
  19.     .text
  20.     .even
  21.     .globl ___addsf3
  22.     .globl __addsf3
  23. ___addsf3:
  24. __addsf3:
  25.     link    a6,#0        | dont need any locals
  26.     moveml    #0x3F00,sp@-    | save all data registers
  27.     movel    a6@(8),d0    | get a
  28.     beq    addsf_ret_b    |  zero .. just return b
  29.     movel    #23,d6        | shift count
  30.     movel    d0,d2        | get the exponent
  31.     lsrl    d6,d2        | and shift right
  32.     andl    #0xFF,d2    | no sign bit
  33.     subl    #126,d2        | offset the exponent
  34.     movel    a6@(12),d1    | get b
  35.     beq    addsf_ret_a
  36.     movel    d1,d3        | get the exponent for b
  37.     lsrl    d6,d3        | and shift right, with implicit extend
  38.     andl    #0xFF,d3    | make sure we didnt get a sign bit
  39.     subl    #126,d3        | off set this one too
  40.  
  41.     andl    #0x7FFFFF,d0    | mask a for mantissa
  42.     orl    #0x800000,d0    | and put in hidden bit
  43.     tstl    a6@(8)        | test the original value
  44.     bpl    addsf_1        | pos, ok
  45.     negl    d0        | neg, negate the mantissa
  46. addsf_1:
  47.     andl    #0x7FFFFF,d1    | mask b for mantissa
  48.     orl    #0x800000,d1    | ditto
  49.     tstl    a6@(12)        | test ...
  50.     bpl    addsf_2
  51.     negl    d1        | negate this one
  52. addsf_2:
  53.     cmpl    d2,d3        | compare Ea to Eb
  54.     blt    addsf_3        | Ea > Eb
  55.  
  56.     movel    d3,d5        | get Eb
  57.     subl    d2,d5        | subtract Ea
  58.     asrl    d5,d0        |  yielding count to shift Ma right
  59.     movel    d3,d5        | use this as resultant exponent
  60.     bra    addsf_4        | and go rejoin common part
  61. addsf_3:
  62.     movel    d2,d5        | get Ea
  63.     subl    d3,d5        | subtract Eb
  64.     asrl    d5,d1        |  yielding count to shift Mb right
  65.     movel    d2,d5        | use this as resultant exponent
  66.  
  67. addsf_4:
  68.     clrl    d7        | zap sign flag
  69.     addl    d1,d0        | add Mb to Ma
  70.  
  71.  
  72.     beq    addsf_z        | zero? ok, go return zero
  73.     bpl    addsf_5        | positive? ok, go scale it
  74.     negl    d0        | negate Mr
  75.     movel    #1,d7        | remember sign
  76. addsf_5:
  77.     btst    #24,d0        | carry?
  78.     beq    addsf_6        | nope, its ok as is
  79.     asrl    #1,d0        | shift right one
  80.     addql    #1,d5        | inc exp
  81.  
  82. | zzz check for overflow in here someplace
  83.  
  84. addsf_6:
  85.     btst    #23,d0        | got a bit in the right place yet?
  86.     bne    addsf_7        | yes, were done
  87.     lsll    #1,d0        | shift left one
  88.     subql    #1,d5        | dec exponent
  89.     bra    addsf_6
  90. addsf_7:
  91.     andl    #0x7FFFFF,d0    | zap out hidden bit
  92.     addl    #126,d5        | add offset to exp
  93.     andl    #0xFF,d5    | zap to 8 bits
  94.     movel    #23,d6        | shift count
  95.     lsll    d6,d5        | shift the exp up
  96.     orl    d5,d0        | stick the exp in
  97.     tstl    d7        | negative?
  98.     beq    addsf_ret_a
  99.     orl    #0x80000000,d0    | yup, negate it
  100.     bra    addsf_ret_a
  101. addsf_z:
  102.     clrl    d0
  103.     bra    addsf_ret_a
  104. addsf_ret_b:
  105.     movel    a6@(12),d0
  106. addsf_ret_a:
  107.     moveml    sp@+,#0x00FC    | snarf back all regs
  108.     unlk    a6
  109.     rts            | sigh
  110. #endif
  111.  
  112. | #ifdef L_negsf2
  113. | int
  114. | _negsf2 (a)
  115. |      union flt_or_int a;
  116. | {
  117. |   union flt_or_int intify;
  118. |   return INTIFY (-a.f);
  119. | }
  120. | #endif
  121.  
  122. #ifdef L_negsf2
  123.     .text
  124.     .even
  125.     .globl ___negsf2
  126.     .globl __negsf2
  127. ___negsf2:
  128. __negsf2:
  129.     movel    sp@(4),d0
  130.     beq    negsf2_z
  131.     eorl    #0x80000000,d0
  132. negsf2_z:
  133.     rts            | sigh
  134. #endif
  135.  
  136. | #ifdef L_subsf3
  137. | int
  138. | _subsf3 (a, b)
  139. |      union flt_or_int a, b;
  140. | {
  141. |   union flt_or_int intify;
  142. |   return INTIFY (a.f - b.f);
  143. | }
  144. | #endif
  145.  
  146. #ifdef L_subsf3
  147.     .text
  148.     .even
  149. .globl ___subsf3
  150. .globl __subsf3
  151. ___subsf3:
  152. __subsf3:
  153.     tstl    sp@(8)        | kludge.  just negate b and add
  154.     beq    subsf_bz    | zero.  dont bother
  155.     eorl    #0x80000000,sp@(8)    | negate it
  156.     jmp    ___addsf3
  157. subsf_bz:
  158.     movel    sp@(4),d0
  159.     rts
  160. #endif
  161.  
  162. | #ifdef L_cmpsf2
  163. | int
  164. | _cmpsf2 (a, b)
  165. |      union flt_or_int a, b;
  166. | {
  167. |   union flt_or_int intify;
  168. |   if (a.f > b.f)
  169. |     return 1;
  170. |   else if (a.f < b.f)
  171. |     return -1;
  172. |   return 0;
  173. | }
  174. | #endif
  175.  
  176. #ifdef L_cmpsf2
  177.     .text
  178.     .even
  179.     .globl ___cmpsf2
  180.     .globl __cmpsf2
  181. ___cmpsf2:
  182. __cmpsf2:
  183.     movel    sp@(4),d0
  184.     movel    sp@(8),d1    | get a hi
  185. |
  186. | crockery.  If both neg and not equal, this algorithm lose.  find a better one!
  187. |
  188.     bpl    cmpsf2_p
  189.     tstl    d0
  190.     bpl    cmpsf2_p
  191.     cmpl    d1,d0
  192.     bgt    cmpsf2_m
  193.     blt    cmpsf2_1
  194.     beq    cmpsf2_z
  195. cmpsf2_p:
  196.     cmpl    d1,d0
  197.     beq    cmpsf2_z
  198.     bgt    cmpsf2_1
  199. cmpsf2_m:
  200.     movel    #-1,d0
  201.     rts
  202. cmpsf2_z:
  203.     clrl    d0
  204.     rts
  205. cmpsf2_1:
  206.     movel    #1,d0
  207.     rts            | sigh
  208. #endif
  209.  
  210. | #ifdef L_mulsf3
  211. | int
  212. | _mulsf3 (a, b)
  213. |      union flt_or_int a, b;
  214. | {
  215. |   union flt_or_int intify;
  216. |   return INTIFY (a.f * b.f);
  217. | }
  218. | #endif
  219.  
  220. #ifdef L_mulsf3
  221.     .text
  222.     .even
  223.     .globl ___mulsf3
  224.     .globl __mulsf3
  225. ___mulsf3:
  226. __mulsf3:
  227. |
  228. | multiply.  take the numbers apart.  shift each exponent down to
  229. | 16 bits.  unsigned multiply those.  shift that down to 24 bits.
  230. | exponent is Ea + Eb.
  231. |
  232.  
  233.     link    a6,#-8        | 64 bit accum for mult
  234.     moveml    #0x3F00,sp@-    | save all data registers
  235.     movel    a6@(8),d0    | get a
  236.     beq    mulsf3_z
  237.     movel    a6@(12),d1    | get b
  238.     beq    mulsf3_z
  239.     movel    #23,d6        | shift count
  240.     movel    d0,d2        | get the exponent
  241.     lsrl    d6,d2        | and shift right
  242.     andl    #0xFF,d2
  243.     subl    #126,d2        | offset the exponent
  244.     movel    d1,d3        | get the exponent for b
  245.     lsrl    d6,d3        | and shift right
  246.     andl    #0xFF,d2
  247.     subl    #126,d3        | off set this one too
  248.  
  249.     clrl    d7        | negative result flag
  250.     andl    #0x7FFFFF,d0    | mask a for mantissa
  251.     orl    #0x800000,d0    | and put in hidden bit
  252.     tstl    a6@(8)        | test the original value
  253.     bpl    mulsf3_1    | pos, ok
  254.     eorl    #1,d7        | remember negative
  255. mulsf3_1:
  256.     andl    #0x7FFFFF,d1    | mask b for mantissa
  257.     orl    #0x800000,d1    | ditto
  258.     tstl    a6@(12)        | test ...
  259.     bpl    mulsf3_2
  260.     eorl    #1,d7
  261. mulsf3_2:
  262. |    lsrl    #8,d1        | shift this one down
  263. |    lsrl    #8,d0        | this one too...
  264. |    mulu    d1,d0        | do the multiply
  265.  
  266. |    beq    mulsf3_ret    | zero? ok, just return
  267. |    lsrl    #8,d0        | shift right again
  268.  
  269. |
  270. | we have mantissas as follows:
  271. |
  272. |    |...ah...|...al...|    |...bh...|...bl...|
  273. |
  274. | product is composed as:
  275. |
  276. |            |....al * bl....|
  277. |        |....al * bh....|
  278. |        |....ah * bl....|
  279. |    |....ah * bh....|
  280. |
  281. | then take the 24 bit chunk thats 16 bits in.
  282.  
  283.     movel    d0,d4
  284.     andl    #0xFFFF,d4    | al
  285.     movel    d1,d5
  286.     andl    #0xFFFF,d5    | bl
  287.     mulu    d5,d4        | thats al * bl
  288.     movel    d4,a6@(-4)    | into the accum
  289.     clrl    a6@(-8)        | zap the top part
  290.  
  291.     movel    d0,d4
  292.     andl    #0xFFFF,d4    | al
  293.     movel    d1,d5
  294.     movel    #16,d6        | shift count
  295.     lsrl    d6,d5        | bh
  296.     mulu    d5,d4        | al * bh
  297.     addl    d4,a6@(-6)
  298.  
  299.     movel    d0,d4
  300.     lsrl    d6,d4        | ah
  301.     movel    d1,d5
  302.     andl    #0xFFFF,d5    | bl
  303.     mulu    d5,d4        | ah * bl
  304.     addl    d4,a6@(-6)
  305.  
  306.     movel    d0,d4
  307.     lsrl    d6,d4        | ah
  308.     movel    d1,d5
  309.     lsrl    d6,d5        | bh
  310.     mulu    d5,d4        | ah * bh
  311.     addl    d4,a6@(-8)
  312.  
  313.     movel    a6@(-6),d0    | get the relevant part
  314.     lsrl    #8,d0        | and shift it down
  315.  
  316. mulsf3_norm:
  317.     btst    #23,d0        | normalized?
  318.     bne    mulsf3_ok
  319.     lsll    #1,d0
  320.     subql    #1,d2
  321.     bra    mulsf3_norm
  322.  
  323. mulsf3_ok:
  324.     andl    #0x7FFFFF,d0    | zap hidden bit
  325.     addl    d3,d2        | add Eb to Ea
  326.     addl    #126,d2        | fix offset
  327.     andl    #0xFF,d2    | whack to 8 bits
  328.     movel    #23,d6        | shift count
  329.     lsll    d6,d2        | shift up to right place
  330.     orl    d2,d0        | shove it in
  331.     tstl    d7        | sign neg?
  332.     beq    mulsf3_ret
  333.     orl    #0x80000000,d0    | set sign bit
  334.     bra    mulsf3_ret
  335. mulsf3_z:
  336.     clrl    d0
  337. mulsf3_ret:
  338.     moveml    sp@+,#0x00FC    | snarf back all regs
  339.     unlk    a6
  340.     rts            | sigh
  341. #endif
  342.  
  343. | #ifdef L_divsf3
  344. | int
  345. | _divsf3 (a, b)
  346. |      union flt_or_int a, b;
  347. | {
  348. |   union flt_or_int intify;
  349. |   return INTIFY (a.f / b.f);
  350. | }
  351. | #endif
  352.  
  353. #ifdef L_divsf3
  354.     .text
  355.     .even
  356.     .globl ___divsf3
  357.     .globl __divsf3
  358. ___divsf3:
  359. __divsf3:
  360. |
  361. | divide.  sort of like mult, exc we do shifts and subtracts to
  362. | do the division of the mantissa.  resultant exponent is Ea - Eb.
  363. |
  364.  
  365.     link    a6,#0        | dont need any locals
  366.     moveml    #0x3F00,sp@-    | save all data registers
  367.     movel    a6@(8),d0    | get a
  368.     movel    a6@(12),d1    | get b
  369.     movel    #23,d6        | shift count
  370.     movel    d0,d2        | get the exponent
  371.     lsrl    d6,d2        | and shift right
  372.     andl    #0xFF,d2
  373.     subl    #127,d2        | offset the exponent
  374.     movel    d1,d3        | get the exponent for b
  375.     lsrl    d6,d3        | and shift right
  376.     andl    #0xFF,d3
  377.     subl    #127,d3        | off set this one too
  378.  
  379.     clrl    d7        | negative result flag
  380.     andl    #0x7FFFFF,d0    | mask a for mantissa
  381.     orl    #0x800000,d0    | and put in hidden bit
  382.     tstl    a6@(8)        | test the original value
  383.     bpl    divsf3_1    | pos, ok
  384.     eorl    #1,d7        | remember negative
  385. divsf3_1:
  386.     andl    #0x7FFFFF,d1    | mask b for mantissa
  387.     orl    #0x800000,d1    | ditto
  388.     tstl    a6@(12)        | test ...
  389.     bpl    divsf3_2
  390.     eorl    #1,d7
  391. divsf3_2:
  392. |
  393. | for now, kludge.  shift Ma left and Mb right, then do an unsigned divide
  394. | and shift the result left.  Blech
  395. |
  396.  
  397. |    lsrl    #8,d1        | shift this one down
  398. |    lsll    #7,d0        | this one up
  399. |    divu    d1,d0        | do the divide
  400. |    andl    #0xFFFF,d0    | and mask off cruft
  401.  
  402. |    beq    divsf3_ret    | zero? ok, just return
  403. |    lsll    #8,d0        | shift left again
  404.  
  405. | same sort of trick as long divide, exc its easier here, cause
  406. | the numbers (mantissas) are already bit-aligned.
  407.  
  408.     clrl    d4        | accumulator
  409.     movel    #0x800000,d5    | bit
  410.     lsll    #7,d0        | buy a little extra accuracy...
  411.     lsll    #7,d1
  412. divsf3_2a:
  413.     cmpl    d1,d0        | compare dividend to divisor
  414.     bmi    divsf3_2b    | nope, no bit here
  415.     orl    d5,d4        | put in the bit
  416.     subl    d1,d0        | and subtract
  417. divsf3_2b:
  418.     lsrl    #1,d1        | slide divisor down
  419.     lsrl    #1,d5        | slide bit down
  420.     bne    divsf3_2a    | and go round again
  421.     movel    d4,d0        | leave the result here
  422.  
  423. divsf3_3:
  424.     btst    #23,d0        | right place yet?
  425.     bne    divsf3_4
  426.     lsll    #1,d0
  427.     subql    #1,d2
  428.     bra    divsf3_3
  429. divsf3_4:
  430.     andl    #0x7FFFFF,d0    | zap hidden bit
  431.     subl    d3,d2        | sub Eb from Ea
  432.     addl    #127,d2        | fix offset
  433.     andl    #0xFF,d2    | whack to 8 bits
  434.     lsll    d6,d2        | shift up to right place
  435.     orl    d2,d0        | shove it in
  436.     tstl    d7        | sign neg?
  437.     beq    divsf3_ret
  438.     orl    #0x80000000,d0    | set sign bit
  439. divsf3_ret:
  440.     moveml    sp@+,#0x00FC    | snarf back all regs
  441.     unlk    a6
  442.  
  443.     rts            | sigh
  444. #endif
  445.